#include <QPainter>
#include <QEvent>
#include <QMouseEvent>
#include "qswitchbutton.h"

SwitchControl::SwitchControl(QWidget *parent)
	: QWidget(parent),
	m_nHeight(20),
	m_bChecked(false),
	m_nMargin(SLIPER_TRACE_MARGIN),
	m_checkedColor(0, 200, 50),
	m_disabledColor(Qt::gray)
{
	setCursor(Qt::PointingHandCursor);

	setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed);

	connect(&m_timer, SIGNAL(timeout()), this, SLOT(onTimeout()));

	m_block_len = 3 * width() / 3;

	m_nX = SLIPER_BLOCK_X;
}

void SwitchControl::paintEvent(QPaintEvent *event)
{
	Q_UNUSED(event);
	
	QPainter painter(this);
	QPainterPath path1, path2, path3;
	QBrush trace_inter_brush(QColor(0, 0, 0));
	QBrush inter_brush(QColor(0, 0, 0));
	
	painter.setRenderHints(QPainter::Antialiasing, true);
	painter.setPen(Qt::NoPen);

	if (m_bChecked) 
	{
		// Draw the sliper trace
		// 1) out
		painter.setBrush(Qt::gray);
		path1.addRoundedRect(0, 0, width(), height(), height() / 2, height() / 2, Qt::AbsoluteSize);
		painter.drawPath(path1);

		// 2) int
		// trace_inter_brush.setStyle(Qt::RadialGradientPattern);
		trace_inter_brush.setColor(QColor(70, 70, 70));
		painter.setBrush(trace_inter_brush);
		qreal ration = (height() - 2 * SLIPER_TRACE_MARGIN) / 2;
		path2.addRoundedRect(SLIPER_TRACE_MARGIN, SLIPER_TRACE_MARGIN, width() - 2 * SLIPER_TRACE_MARGIN, height() - 2 * SLIPER_TRACE_MARGIN, ration, ration, Qt::AbsoluteSize);
		painter.drawPath(path2);

		// Draw outer sliper block
		qreal block_dia = height() - 2 * SLIPER_BLOCK_Y;
		QBrush block_outer_brush(this->palette().background());
		// block_outer_brush.setStyle(Qt::RadialGradientPattern);
		painter.setBrush(block_outer_brush);
		painter.setOpacity(1.0);
		path3.addRoundedRect(m_nX, SLIPER_BLOCK_Y, m_block_len, block_dia, block_dia / 2, block_dia / 2, Qt::AbsoluteSize);
		// painter.drawEllipse(m_nX, SLIPER_BLOCK_Y, block_dia, block_dia);
		painter.drawPath(path3);

		// Draw the inter sliper block
		inter_brush.setColor(m_checkedColor);
		qreal inter_x = m_nX + m_block_len + block_dia / 2 - SLIPER_BLOCK_INTER_R - block_dia;
		qreal inter_y = SLIPER_BLOCK_Y + block_dia / 2 - SLIPER_BLOCK_INTER_R;
		painter.setBrush(inter_brush);
		painter.setOpacity(1.0);
		painter.drawEllipse(inter_x, inter_y, 2 * SLIPER_BLOCK_INTER_R, 2 * SLIPER_BLOCK_INTER_R);
	}
	else 
	{
		// Draw the sliper trace
		// 1) out
		painter.setBrush(Qt::gray);
		path1.addRoundedRect(0, 0, width(), height(), height() / 2, height() / 2, Qt::AbsoluteSize);
		painter.drawPath(path1);
		// trace_inter_brush.setStyle(Qt::RadialGradientPattern);
		trace_inter_brush.setColor(QColor(70, 70, 70));
		painter.setBrush(trace_inter_brush);

		// 2) int
		// trace_inter_brush.setStyle(Qt::RadialGradientPattern);
		trace_inter_brush.setColor(QColor(70, 70, 70));
		painter.setBrush(trace_inter_brush);
		qreal ration = (height() - 2 * SLIPER_TRACE_MARGIN) / 2;
		path2.addRoundedRect(SLIPER_TRACE_MARGIN, SLIPER_TRACE_MARGIN, width() - 2 * SLIPER_TRACE_MARGIN, height() - 2 * SLIPER_TRACE_MARGIN, ration, ration, Qt::AbsoluteSize);
		painter.drawPath(path2);

		// Draw outer sliper block
		qreal block_dia = height() - 2 * SLIPER_BLOCK_Y;
		QBrush block_outer_brush(this->palette().background());
		// block_outer_brush.setStyle(Qt::RadialGradientPattern);
		painter.setBrush(block_outer_brush);
		painter.setOpacity(1.0);
		path3.addRoundedRect(m_nX, SLIPER_BLOCK_Y, m_block_len, block_dia, block_dia / 2, block_dia / 2, Qt::AbsoluteSize);
		// painter.drawEllipse(m_nX, SLIPER_BLOCK_Y, block_dia, block_dia);
		painter.drawPath(path3);

		// Draw the inter sliper block
		inter_brush.setColor(m_disabledColor);
		qreal inter_x = m_nX + m_block_len + block_dia / 2 - SLIPER_BLOCK_INTER_R - block_dia;
		qreal inter_y = SLIPER_BLOCK_Y + block_dia / 2 - SLIPER_BLOCK_INTER_R;
		painter.setBrush(inter_brush);
		painter.setOpacity(1.0);
		painter.drawEllipse(inter_x, inter_y, 2 * SLIPER_BLOCK_INTER_R, 2 * SLIPER_BLOCK_INTER_R);
	}
}

void SwitchControl::mousePressEvent(QMouseEvent *event)
{
	if (isEnabled()) {
		if (event->buttons() & Qt::LeftButton) {
			event->accept();
		}
		else {
			event->ignore();
		}
	}
}

void SwitchControl::mouseReleaseEvent(QMouseEvent *event)
{
	if (isEnabled()) {
		if ((event->type() == QMouseEvent::MouseButtonRelease) && (event->button() == Qt::LeftButton)) {
			event->accept();
			// m_bChecked = !m_bChecked;
			emit toggled(!m_bChecked);
			// Do not update switch button's widget as the actul operation could encouter an error,
			// which means that can NOT switch the right status.
			// m_timer.start(SLIPER_TIME_MS);
		}
		else {
			event->ignore();
		}
	}
}

void SwitchControl::resizeEvent(QResizeEvent *event)
{
	QSize oldSize;
	m_block_len = 2 * width() / 3;
	QWidget::resizeEvent(event);
}

QSize SwitchControl::sizeHint() const
{
	return minimumSizeHint();
}

QSize SwitchControl::minimumSizeHint() const
{
	int h = m_nHeight + 2 * m_nMargin;
	return QSize(2.5*h, h);
}

void SwitchControl::onTimeout()
{
	qreal block_dia = height() - 2 * SLIPER_BLOCK_Y;

	if (m_bChecked) 
	{
		m_nX += SLIPER_MOVE_STEP;
		if (m_nX >= width() - SLIPER_BLOCK_X - m_block_len)
		{
			m_nX = width() - SLIPER_BLOCK_X - m_block_len;
			m_timer.stop();
		}
	}
	else 
	{
		m_nX -= SLIPER_MOVE_STEP;
		if (m_nX <= SLIPER_BLOCK_X)
		{
			m_nX = SLIPER_BLOCK_X;
			m_timer.stop();
		}
	}
	update();
}

bool SwitchControl::isToggled() const
{
	return m_bChecked;
}

void SwitchControl::setToggle(bool checked)
{
	m_bChecked = checked;
	m_timer.start(SLIPER_TIME_MS);
}

void SwitchControl::setCheckedColor(QColor color)
{
	m_checkedColor = color;
}

void SwitchControl::setDisbaledColor(QColor color)
{
	m_disabledColor = color;
}
